From Tables S1 and S2 in: Kantsa, A., R.A. Raguso, A.G. Dyer, J.M. Olesen, T. Tscheulin, and T. Petanidou. 2018. Disentangling the role of floral sensory stimuli in pollination networks. Nature Communications 9: 1041. doi:[10.1038/s41467-018-03448-w](https://doi.org/10.1038/s41467-018-03448-w)
#load network
net <- read.delim("Kantsa_etal_Supp_Data1.csv", skip = 2)
rownames(net) <- net[,1]
net[,1] <- NULL
net <- as.matrix(t(net))
polls <- colnames(net)
snet <- sortweb(net) #sort by row & column totals
#load floral scents
scent.file <- "Kantsa_2018_Supp_Data2.xlsx"
plants <- getSheetNames(scent.file)
scentlist <- lapply(2:length(plants), read.xlsx, xlsxFile=scent.file)
plants <- plants[-1]
scent <- rbindlist(scentlist, fill=T, idcol="plant")[,-4]
colnames(scent)[2:3] <- c("cmpd","mean")
scent$plant <- factor(plants[scent$plant])
scent$cmpd <- factor(tolower(scent$cmpd))
cmpds <- levels(scent$cmpd)
scent.net <- dcast(scent, plant ~ cmpd, value.var="mean", fun.aggregate=mean, fill=0) #long to wide
scent.net <- as.data.frame(scent.net)
rownames(scent.net) <- scent.net[,1]
scent.net[,c(1,380)] <- NULL #weird NA column has one entry
scent.net <- as.matrix(scent.net)
#plants.class <- classification(plants, db="gbif")
#save(plants.class, file="plantsclass.Rdata")
load("plantsclass.Rdata")
plants.classtree <- class2tree(plants.class) #taxonomic tree
plants.tree <-phylomatic(taxa=names(plants.class), get = 'POST', storedtree="zanne2014")
plants.tree$tip.label[order(plants.tree$tip.label)] <- plants
par(mar=c(0,0,0,0))
cp <- cophylo(plants.tree, plants.classtree$phylo)
Rotating nodes to optimize matching...
Done.
plot(cp)
polls <- gsub("Bug", "Hemiptera", polls, fixed=T)
polls <- gsub("Auchenorrhyncha", "Hemiptera", polls, fixed=T)
polls <- gsub("Fly", "Diptera", polls, fixed=T)
polls <- gsub("Beetle", "Coleoptera", polls, fixed=T)
#polls.class <- classification(polls, db="gbif")
#save(polls.class, file="pollsclass.Rdata")
load("pollsclass.Rdata")
polls.gbif <- factor(sapply(polls.class, function(x) tail(x$name, 1)))
net.lump <- aggregate(.~ polls.gbif, as.data.frame(t(net)), sum)
rownames(net.lump) <- net.lump[,1]
net.lump[,1] <- NULL
net.lump <- as.matrix(t(net.lump))
rownames(net.lump) <- sort(plants.tree$tip.label)
polls.classtree <- class2tree(unique(polls.class)) #taxonomic tree
polls.matched <- tnrs_match_names(lapply(polls.class, function(x) tail(x$name, 1)), context_name = "Animals")
Warning: Some names were duplicated: 'andrena', 'asilidae', 'coleoptera',
'hemiptera', 'buprestidae', 'buprestidae', 'calliphoridae', 'cerambycidae',
'chrysididae', 'crabronidae', 'eumenidae', 'eumenidae', 'eumenidae',
'diptera', 'diptera', 'diptera', 'diptera', 'diptera', 'hoplitis',
'hoplitis', 'lasioglossum', 'noctuidae', 'oedemera', 'osmia', 'osmia'.
Warning in check_tnrs(res): chrysura circe are not matched
polls.ids <- ott_id(polls.matched)
polls.ids <- polls.ids[!polls.ids %in% c(968359, 707236, 707875, 63881, 458953, 42699, 742352, 340559, 672497, 34898, 332969,356987)]
polls.tree <- tol_induced_subtree(ott_ids=polls.ids)
Progress [-----------------------------------] 0/7 ( 0%) ?s
Progress [==================================] 7/7 (100%) 0s
Warning in collapse_singles(tr): Dropping singleton nodes with labels:
Colletes ott115493, Crabronidae ott372234, Scolia ott881314, Coleoptera
ott865243, Diptera ott661378, Paragus ott973598, Hemiptera ott603650
par(mar=c(0,0,0,0))
plot(polls.classtree, cex=0.5)
plot(polls.tree, cex=0.5)
mnet.lump <- melt(net.lump)
mnet.lump <- mnet.lump[mnet.lump$value>0,]
cophyloplot(plants.tree, polls.classtree$phylo, mnet.lump[,1:2], lwd=sqrt(mnet.lump[,3])/4, show.tip.label=F, col='steelblue', length.line=0, gap=-20, space=60)
polls.cut <- dendextend::cutree(polls.classtree$phylo,5)
polls.order <- setNames(factor(sapply(unique(polls.class), function(x) x$name[4])), names(polls.class[!duplicated(polls.class)]))
polls.order.all <- setNames(factor(sapply(polls.class, function(x) x$name[4])),names(polls.class))
#table(polls.cut, polls.order)
net.grp <- aggregate(.~ polls.order.all, as.data.frame(t(net)), sum)
rownames(net.grp) <- net.grp[,1]
net.grp[,1] <- NULL
net.grp <- as.matrix(t(net.grp))
rownames(net.grp) <- sort(plants.tree$tip.label)
plants.majorpoll <- setNames(factor(colnames(net.grp)[apply(net.grp, 1, which.max)]), rownames(net.grp))
pcols <- setNames(brewer.pal(4,"Set1"), levels(plants.majorpoll))
plants.polltrees<-make.simmap(plants.tree,plants.majorpoll,model="ARD",nsim=100)
make.simmap is sampling character histories conditioned on the transition matrix
Q =
Coleoptera Diptera Hymenoptera Lepidoptera
Coleoptera -0.008667015 0.0006377689 0.008029247 0.00000000
Diptera 0.017012461 -0.0224322446 0.005419784 0.00000000
Hymenoptera 0.000000000 0.0000000000 -0.071181044 0.07118104
Lepidoptera 0.078649350 0.0796271485 1.270049241 -1.42832574
(estimated using likelihood);
and (mean) root node prior probabilities
pi =
Coleoptera Diptera Hymenoptera Lepidoptera
0.25 0.25 0.25 0.25
Done.
plants.polltree<-summary(plants.polltrees,plot=FALSE)
plot(plants.polltree,colors=pcols,fsize=0.8,cex=c(0,0.3))
add.simmap.legend(colors=pcols,x=0.9*par()$usr[1],
y=0.2*par()$usr[4],prompt=FALSE,fsize=0.9)
heatmaply(net, scale="column", row_side_colors = data.frame(plants.majorpoll), row_side_palette=function(n) pcols)
#interaction matrix plot
visweb(net, type="nested", circles=T, boxes=F, circle.max=1.2)
#interaction web plot
pcols.all <- setNames(c(pcols[1:2],brewer.pal(5,"Set1")[5],pcols[3:4]), levels(polls.order.all))
plotweb(sqrt(net), empty=F, text.rot=90, method="cca", col.high=pcols.all[polls.order.all], col.low=pcols[plants.majorpoll], col.interaction=pcols.all[polls.order.all], bor.col.interaction=pcols.all[polls.order.all], bor.col.high=pcols.all[polls.order.all], bor.col.low=pcols[plants.majorpoll])
networklevel(net)
connectance web asymmetry
0.06312657 0.63106796
links per species number of compartments
1.95631068 2.00000000
compartment diversity cluster coefficient
1.07901412 0.02631579
nestedness weighted nestedness
4.47259022 0.58578362
weighted NODF interaction strength asymmetry
10.80348739 0.20372363
specialisation asymmetry linkage density
-0.04424002 3.57255189
weighted connectance Fisher alpha
0.01734248 89.61252715
Shannon diversity interaction evenness
3.27629195 0.37393976
Alatalo interaction evenness H2
0.25285628 0.57919894
number.of.species.HL number.of.species.LL
168.00000000 38.00000000
mean.number.of.shared.partners.HL mean.number.of.shared.partners.LL
0.34944397 1.18776671
cluster.coefficient.HL cluster.coefficient.LL
0.34062967 0.21733898
weighted.cluster.coefficient.HL weighted.cluster.coefficient.LL
0.72421977 0.31277076
niche.overlap.HL niche.overlap.LL
0.12366249 0.14889538
togetherness.HL togetherness.LL
0.03019814 0.02302573
C.score.HL C.score.LL
0.75923950 0.74100046
V.ratio.HL V.ratio.LL
3.23242952 17.02718828
discrepancy.HL discrepancy.LL
248.00000000 250.00000000
extinction.slope.HL extinction.slope.LL
4.79325165 1.62192500
robustness.HL robustness.LL
0.80798877 0.61786266
functional.complementarity.HL functional.complementarity.LL
8044.31456516 7651.23911634
partner.diversity.HL partner.diversity.LL
0.94103312 1.28483306
generality.HL vulnerability.LL
2.67434342 4.47076037
heatmaply(scent.net, scale="column", row_side_colors = data.frame(plants.majorpoll), row_side_palette=function(n) pcols)
#interaction web plot
plotweb(sqrt(scent.net), text.rot=90, method="cca", col.high=pal[2], bor.col.high=pal[2], col.low=pcols[plants.majorpoll], bor.col.low=pcols[plants.majorpoll], col.interaction=pal[5], bor.col.interaction=pal[5])
scent.mds <- metaMDS(sqrt(scent.net), autotransform = F, trace=F)
#scent.op <- ordiplot(scent.mds, type="n")
#points(scent.op, what="species", pch=3, col="grey50")
#points(scent.op, what="sites", cex=1.5, pch=19, col=pcols[plants.majorpoll])
#text(scent.op, what="sites", cex=0.8, col=pcols[plants.majorpoll])
scent.mds.taxa <- scent.mds$points
rownames(scent.mds.taxa) <- sort(plants.tree$tip.label)
rownames(scent.mds.taxa) <- gsub(" ", "_", rownames(scent.mds.taxa), fixed=T)
plants.tree$tip.label <- gsub(" ", "_", plants.tree$tip.label, fixed=T)
#plants.tree$phylo$edge.length <- plants.tree$phylo$edge.length+0.00001
tip.pcols <- setNames(pcols[plants.majorpoll],
sort(plants.tree$tip.label))
node.pcols<- setNames(c(tip.pcols[plants.tree$tip.label], rep("black",plants.tree$Nnode)),
1:(length(plants.tree$tip)+plants.tree$Nnode))
phylomorphospace(plants.tree, scent.mds.taxa, control=list(col.node=node.pcols), node.size=c(0,1), label="off", lwd=1)
text(scent.mds.taxa[,1], scent.mds.taxa[,2], rownames(scent.mds.taxa), cex=0.8, offset=0.5, xpd=T, col=tip.pcols)
library(vegan3d)
orditree3d(scent.mds.taxa, as.hclust(force.ultrametric(multi2di(plants.tree))), lwd=2, pch=19, col=tip.pcols)
png(file="ppm-%04d.png",width=600,height=600,res=120)
par(mar=c(2.1,2.1,1.1,1.1))
project.phylomorphospace(tree=plants.tree, X=scent.mds.taxa, xlab="", ylab="", node.size=c(0,0), lwd=1, direction="to", nsteps=100, fsize=0.6)
dev.off()
system("convert -delay 10 -loop 2 *.png phylochemo.gif")
file.remove(list.files(pattern=".png"))
ccol = sample(rainbow(ncol(scent.net)))
par(mfrow=c(1,2))
par(mar=c(0.8,0,0.8,0))
plot(plants.tree, cex=1, tip.color = tip.pcols)
par(mar=c(0,0,0,0))
barplot(t(scent.net), col=ccol, names.arg=rep("",nrow(scent.net)), horiz=TRUE)
par(mfrow=c(1,2))
par(mar=c(0.8,0,0.8,0))
plot(plants.tree, cex=1, tip.color = tip.pcols)
par(mar=c(0,0,0,0))
barplot(t(decostand(scent.net, method="tot")), col=ccol, names.arg=rep("",nrow(scent.net)), horiz=TRUE)